package com.example.emos.wx.controller;

/**
 * @ClassName : UserController
 * @Author : 骆发茂
 * @Date: 2021/10/13 20:46
 * @Description :实现注册超级管理员功能（Web层）
 */


import com.example.emos.wx.common.util.R;
import com.example.emos.wx.config.shiro.JwtUtil_根据ID生成_解密获ID_验证TOKEN;
import com.example.emos.wx.controller.form.LoginForm;
import com.example.emos.wx.controller.form.RegisterForm;
import com.example.emos.wx.service.UserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.HashMap;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * 实现注册超级管理员功能（Web层）
 * 处理移动端提交的请求、controller层
 * 问:
 * :业务层采用先定义接口，后声明实现类的做法，为什么Web层不这么做?
 * 答:
 * ：业务层的需求经常变化，所以应该先声明接口，然后再写实现类。Web层这里变化并不大，可以直接定义具体类。
 */



@RestController
@Api("用户模块web接口")
@RequestMapping("/user")/**分配请求的路径*/
/**vue:实现MVM架构，视图层，模型层，中间加层，即VUEmodel，传递数据和事件；
 * 数据带回到页面，数据里面加参数，MVM中的model，waiter，
 * 游走于视图和模型层之间传递数据和事件；vue对象传参，vue对象当作搬运工
 * el属性，为哪一个对象服务；data属性：js属性，被表达式传到页面上，就是vue对象传递在视图层、模型层
 * 如何绑定数据？js里面都有prototype属性的，通过prototype绑定在vue对象上，使用vue对象绑定的prototype*/
public class UserController {

    /*调用业务层代码*/
    @Autowired
    private UserService userService;


    /*用户注册成功后，向客户端返回jwt生成的令牌字符串*/
    @Autowired
    private JwtUtil_根据ID生成_解密获ID_验证TOKEN jwtUtil生成解密验证TOKEN;


    /*将令牌不仅要缓存到客户端，还要到redis里面*/
    @Autowired
    private RedisTemplate redisTemplate;


    @Value("${emos.jwt.cache-expire}")
    private int cacheExpire;


    @PostMapping("/register")/**只接受POST请求*/
    @ApiOperation("注册用户")
    /*Valid，验证传入的数据，
     * @RequestBody主要用来接收   前端传递给后端的   json字符串中的数据的(请求体中的数据的)；      可以是对象，可以是数据
     * */

    /**根据     传进来的form表单的数据，   生成token，并且根据id查找权限，将权限和token返回给客户端，将token存入redis中*/
    public R register(@Valid @RequestBody RegisterForm form) {
        /*根据service层的方法registerUser注册用户，返回用户id*/
        int id = userService.registerUser(form.getRegisterCode(), form.getCode(), form.getNickname(), form.getPhoto());
        /*根据ID生成token字符串*/
        String token = jwtUtil生成解密验证TOKEN.createToken(id);
        /*不仅向客户端返回token字符串（认证了），还要返回权限（给权限）*/
        Set<String> permsSet = userService.searchUserPermissions(id);
        /*向redis缓存token*/
        saveCacheToken(token, id);
        /*向客户端返回数据，返回注册的信息、令牌字符串、权限*/
        return R.ok("用户注册成功").put("token", token).put("permission", permsSet);
    }


    /*向redis缓存token*/
    private void saveCacheToken(String token, int userId) {
        /*保存数据，key是token，value是id，刷新令牌，以后可以根据对应的id刷新令牌，可以根据userid重新生令牌*/
        /**set(K key, V value, long timeout, TimeUnit unit)
         设置变量值的过期时间。*/
        redisTemplate.opsForValue().set(token, userId, cacheExpire, TimeUnit.DAYS);
    }



    /**实现用户登陆功能（Web层）*/
    /**前端发送来的临时字符串code，后端Java接收后
     * 查找id，根据id生成token，根据id查找权限，返回给前端信息，token，permission*/
    @PostMapping("/login")
    @ApiOperation("登陆系统")
    /*Valid，验证传入的数据，
     * @RequestBody主要用来接收 前端传递给后端的 json字符串中的数据的(请求体中的数据的) ；可以是对象，可以是数据
     * */
    public R login(@Valid @RequestBody/**接收json数据*/ LoginForm form){
        /*根据code，service-dao-xml中获取到对应的id，登录*/
        Integer id = userService.login(form.getCode());
        /*根据用户的id生成token，令牌*/
        String token = jwtUtil生成解密验证TOKEN.createToken(id);
        /*根据id搜索用户的权限，不重复set*/
        Set<String> permsSet = userService.searchUserPermissions(id);
        /*保留token 以及对应 id*/
        saveCacheToken(token, id);
        /*返回 权限、令牌*/
        return R.ok("登录成功").put("token",token).put("permission",permsSet);

    }


    /** 这里controller，传进来的是token，根据token拿出userid
     *     8-11实现用户页面数据加载(13-54)
     *      移动端：我的栏目，前端需要显示用户名，部门情况、头像*/


    /**	onshow: function() {
     let that = this;
     that.ajax(that.url.searchUserSummary, 'GET', null, function(resp) {
     let result = resp.data.result;
     that.name = result.name;
     that.deptName = result.deptName;
     that.photo = result.photo;
     });
     },前端预览*/
    @GetMapping("/searchUserSummary")
    @ApiOperation("查询用户摘要信息")
    public R searchUserSummary(@RequestHeader("token") String token){
        /*根据token拿出userid*/
        Integer userId = jwtUtil生成解密验证TOKEN.getUserId(token);
        HashMap map = userService.searchUserSummary(userId);
        /**为什么叫result，不叫其他的，因为和前端约定了传输数据的参数为result
         * 前端接收数据的时候接收的是        resp.data.result*/
        return R.ok().put("result",map);

    }}